using System;
using System.Web;
using System.Text;
using System.Collections.Generic;
using IndiGoGameProcessor.Arithmetic;

namespace IndiGoGameProcessor.Board
{
	public class BoardEncoder : IBoardEncoder
	{
		/// <summary>
		/// Encodes the board.
		/// </summary>
		/// <returns> A URL safe base64 string uniquely representing the board.</returns>
		/// <param name='board'> Board </param>
		public string EncodeBoard(Board board)
		{
			//At the moment the byte list comes out one byte too short :-(
			
			var byteList = new List<byte>();
			var b3 = new Base3Handler();
			
			var trits = new List<byte>();
			foreach(var intersect in board)
			{
				//Build a list of 5 intersects as bytes
				trits.Add((byte)intersect);
				if(trits.Count == 5)
				{
					byteList.Add(b3.CreateByteFromTrits(trits));
					trits = new List<byte>();
				}
			}
			//Mop up any left overs
			if(trits.Count > 0)
			{
				byteList.Add(b3.CreateByteFromTrits(trits));
			}
			return  HttpServerUtility.UrlTokenEncode(byteList.ToArray());
		}
		
		/// <summary>
		/// Decodes the board.
		/// </summary>
		/// <returns> The board. </returns>
		/// <param name='encodedBoard'> Encoded Board </param>
		/// <param name='width'> Board width </param>
		public Board DecodeBoard(string encodedBoard, int width) //Todo: remove the requirement for width here...
		{
			var boardAsBytes = new List<byte>(HttpServerUtility.UrlTokenDecode(encodedBoard));
			var boardAsTrits = new List<byte>();
			
			var b3 = new Base3Handler();
			
			foreach(var theByte in boardAsBytes)
			{
				boardAsTrits.AddRange(b3.CreateTritsFromByte(theByte));
			}
			
			return new Board(boardAsTrits, width);
		}
	}
}
		
